<template>
  <transition :name="transitionName">
    <div v-show="visible" class="back-to-ceiling" @click="backToTop">
      <van-icon name="back-top" />
    </div>
  </transition>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, reactive } from 'vue'
import { useRouter } from 'vue-router'
const props = defineProps({
  visibilityHeight: {
    type: Number,
    default: 400,
  },
  backPosition: {
    type: Number,
    default: 0,
  },
  transitionName: {
    type: String,
    default: 'fade',
  },
})
let visible = ref(false)
let interval: any = ref(null)
let isMoving = ref(false)
const easeInOutQuad = (time: number, b: number, c: number, d: number) => {
  let t = time
  if ((t /= d / 2) < 1) return (c / 2) * t * t + b
  return (-c / 2) * ((t -= 1) * (t - 2) - 1) + b
}

const backToTop = () => {
  if (isMoving.value) return
  const start = window.scrollY
  let i = 0
  isMoving.value = true
  interval = setInterval(() => {
    const next = Math.floor(easeInOutQuad(10 * i, start, -start, 500))
    if (next <= props.backPosition) {
      window.scrollTo(0, props.backPosition)
      clearInterval(interval)
      isMoving.value = false
    } else {
      window.scrollTo(0, next)
    }
    i += 1
  }, 16.7)
}
const init = () => {
  window.addEventListener('scroll', handleScroll)
}
const destroy = () => {
  window.removeEventListener('scroll', () => {
    handleScroll()
  })
  if (interval) {
    clearInterval(interval)
  }
}
const handleScroll = () => {
  visible.value = window.scrollY > props.visibilityHeight
}
const useRouterCurrent = reactive(useRouter())
watch(useRouterCurrent, () => {
  init()
  destroy()
})
onMounted(() => {
  init()
})
onBeforeUnmount(() => {
  destroy()
})
</script>

<style lang="scss" scoped>
.back-to-ceiling {
  position: fixed;
  z-index: 1000;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #f5f5f5;
  right: 10px;
  bottom: 22%;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  box-shadow: 0 1px 8px rgba(0, 21, 41, 0.08);
  .van-icon {
    font-size: 40px;
  }
}
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s;
}

.fade-enter,
.fade-leave-to {
  opacity: 0;
}
</style>
